package com.carter.springframework.beans.factory;

import com.carter.springframework.beans.exception.BeanException;
import com.carter.springframework.beans.factory.config.BeanDefinition;
import com.carter.springframework.beans.factory.config.PropertyValue;
import com.carter.springframework.beans.factory.config.PropertyValues;
import com.carter.springframework.beans.factory.support.BeanFactoryPostProcessor;
import com.carter.springframework.core.io.DefaultResourceLoader;
import com.carter.springframework.core.io.Resource;
import com.carter.springframework.util.StringValueResolver;

import java.io.IOException;
import java.util.Properties;

/**
 * 处理spring配置中的占位符${xxx},替换为真正的值
 */
public class PropertyPlaceholderConfigurer implements BeanFactoryPostProcessor {
    public static final String DEFAULT_PLACEHOLDER_PREFIX = "${";;

    public static final String DEFAULT_PLACEHOLDER_SUFFIX = "}";

    /**
     * 保存变量值的配置文件位置
     */
    private String location;

    public void setLocation(String location) {
        this.location = location == null ? null : location.trim();
    }

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {

        try {
            //通过之前实现的resourceLoader将配置文件的内容读取到properties中
            DefaultResourceLoader resourceLoader = new DefaultResourceLoader();
            Resource resource = resourceLoader.getResource(location);
            Properties properties = new Properties();
            properties.load(resource.getInputStream());
            String[] beanDefinitionNames = beanFactory.getBeanDefinitionNames();
            //对bean定义进行遍历
            for (String beanName : beanDefinitionNames) {
                BeanDefinition beanDefinition = beanFactory.getBeanDefinition(beanName);
                //拿到bean定义中的所有依赖属性
                PropertyValues propertyValues = beanDefinition.getPropertyValues();
                //对所有属性进行遍历
                for (PropertyValue pv : propertyValues.getPropertyValues()) {
                    Object value = pv.getValue();
                    if (!(value instanceof String)){
                        continue;
                    }
                    /**
                    String strValue = (String) value;
                    StringBuilder sb = new StringBuilder(strValue);
                    int startIndex = strValue.indexOf(DEFAULT_PLACEHOLDER_PREFIX);
                    int endIndex = strValue.indexOf(DEFAULT_PLACEHOLDER_SUFFIX);
                    if (-1!=startIndex&&-1!=endIndex&&startIndex<endIndex){
                        String propKey = strValue.substring(startIndex + 2, endIndex);
                        String propValue = properties.getProperty(propKey);
                        sb.replace(startIndex,endIndex+1,propValue);
                        propertyValues.addPropertyValue(new PropertyValue(pv.getName(),sb.toString()));
                    }*/
                    value = resolvePlaceholder((String) value,properties);
                    propertyValues.addPropertyValue(new PropertyValue(pv.getName(),value));

                }
            }
            //添加字符串解析器，供解析@Value注解使用
            PlaceholderResolvingStringValueResolver resolver = new PlaceholderResolvingStringValueResolver(properties);
            beanFactory.addEmbeddedValueResolver(resolver);
        } catch (IOException e) {
            throw new BeanException("加载配置时出错",e);
        }
    }

    private class PlaceholderResolvingStringValueResolver implements StringValueResolver{
        private final Properties properties;

        public PlaceholderResolvingStringValueResolver(Properties properties) {
            this.properties = properties;
        }

        @Override
        public String resolveStringValue(String value) {
            //这种写法等效于this，但这样写能够体现出resolvePlaceholder这个方法是PropertyPlaceholderConfigurer这个类的
            return PropertyPlaceholderConfigurer.this.resolvePlaceholder(value,properties);
        }
    }

    /**
     * 处理占位符
     * @param value
     * @param properties
     * @return
     */
    private String resolvePlaceholder(String value, Properties properties) {
        StringBuilder builder = new StringBuilder(value);
        int startIdx = value.indexOf(DEFAULT_PLACEHOLDER_PREFIX);
        int stopIdx = value.indexOf(DEFAULT_PLACEHOLDER_SUFFIX);
        if (startIdx != -1 && stopIdx != -1 && startIdx < stopIdx) {
            String propKey = value.substring(startIdx + 2, stopIdx);
            String propVal = properties.getProperty(propKey);
            builder.replace(startIdx, stopIdx + 1, propVal);
        }
        return builder.toString();
    }
}
